package com.srmt.document.feishu.internal.table.impl.sheet;

import com.lark.oapi.service.docx.v1.model.*;
import com.srmt.document.exception.TableException;
import com.srmt.document.feishu.internal.table.model.TableContext;
import com.srmt.document.feishu.internal.table.util.SheetCoordinateHelper;
import com.srmt.document.model.RowData;
import com.srmt.document.model.TableData;
import com.srmt.feishu.client.FeishuClient;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;

/**
 * 电子表格读取操作
 *
 * 封装所有与Sheet读取相关的操作，包括：
 * - 单元格内容读取
 * - 表格维度获取
 * - 合并单元格信息
 * - 表格数据转换
 *
 * @author srmt
 * @since 3.0.0
 */
public class SheetReadOperations {

    private static final Logger logger = LoggerFactory.getLogger(SheetReadOperations.class);

    private final FeishuClient client;

    public SheetReadOperations(FeishuClient client) {
        if (client == null) {
            throw new IllegalArgumentException("客户端不能为null");
        }
        this.client = client;
    }

    /**
     * 获取单元格内容
     *
     * @param context 表格上下文
     * @param row 行索引（1-based）
     * @param col 列索引（1-based）
     * @return 单元格内容
     * @throws TableException 操作失败时抛出
     */
    public String getCellContent(TableContext context, int row, int col) throws TableException {
        logger.debug("获取 sheet cell [{}, {}] content", row, col);

        Block tableBlock = context.getTableBlock();
        if (tableBlock.getSheet() == null) {
            throw new TableException("块中未找到电子表格信息");
        }

        String token = tableBlock.getSheet().getToken();
        if (token == null || token.isEmpty()) {
            logger.warn("电子表格令牌为空,返回空内容");
            return "";
        }

        try {
            // 解析token获取spreadsheetToken和sheetId
            String[] parts = SheetCoordinateHelper.parseSheetToken(token);
            String spreadsheetToken = parts[0];
            String sheetId = parts.length > 1 ? parts[1] : "";

            // 构建单个单元格的范围（使用相同的起始和结束坐标）
            String range = SheetCoordinateHelper.buildRange(sheetId, row, col, row, col);

            logger.debug("从范围读取单元格内容: {}", range);

            // 使用范围读取API获取单元格内容
            List<List<String>> values = client.sheets().getValues(spreadsheetToken, range);

            if (values != null && !values.isEmpty() && !values.get(0).isEmpty()) {
                return values.get(0).get(0);
            }

            return "";

        } catch (Exception e) {
            logger.error("获取单元格内容失败: {}", e.getMessage());
            return "";
        }
    }

    /**
     * 获取表格维度
     *
     * @param context 表格上下文
     * @return [行数, 列数]
     * @throws TableException 操作失败时抛出
     */
    public int[] getTableDimensions(TableContext context) throws TableException {
        logger.debug("获取工作表的维度: {}", context.getTableBlockId());

        Block tableBlock = context.getTableBlock();
        if (tableBlock.getSheet() == null) {
            throw new TableException("块中未找到电子表格信息");
        }

        Sheet sheet = tableBlock.getSheet();

        // 首先尝试从Sheet对象中获取维度信息
        if (sheet.getRowSize() != null && sheet.getColumnSize() != null) {
            int rows = sheet.getRowSize();
            int cols = sheet.getColumnSize();
            logger.debug("电子表格 dimensions from block: {} x {}", rows, cols);
            return new int[]{rows, cols};
        }

        // 如果Sheet对象没有维度信息，尝试通过API获取
        String token = sheet.getToken();
        if (token == null || token.isEmpty()) {
            // 没有token，使用默认值
            logger.warn("没有工作表令牌,使用默认维度");
            return new int[]{10, 10}; // 默认10x10
        }

        try {
            // 解析token
            String[] parts = SheetCoordinateHelper.parseSheetToken(token);
            String spreadsheetToken = parts[0];
            String sheetId = parts[1];

            if (!sheetId.isEmpty()) {
                // 有具体的sheetId，尝试获取sheet信息
                logger.debug("尝试获取工作表信息: {} / {}", spreadsheetToken, sheetId);

                // getSheet现在直接返回Sheet对象，失败时抛出FeishuApiException
                com.lark.oapi.service.sheets.v3.model.Sheet sheetData =
                    client.sheets().getSheet(spreadsheetToken, sheetId);

                if (sheetData != null) {
                    // 获取网格属性
                    if (sheetData.getGridProperties() != null) {
                        int rows = sheetData.getGridProperties().getRowCount();
                        int cols = sheetData.getGridProperties().getColumnCount();

                        logger.debug("电子表格 dimensions from API: {} x {}", rows, cols);
                        return new int[]{rows, cols};
                    }
                }
            }

            // 如果无法获取具体信息，使用默认值
            logger.warn("无法从API获取工作表维度,使用默认值");
            return new int[]{100, 26}; // 默认100行26列

        } catch (Exception e) {
            logger.warn("从API获取工作表维度失败: {}, using defaults", e.getMessage());
            return new int[]{100, 26}; // 默认100行26列
        }
    }

    /**
     * 获取表格合并信息
     *
     * @param context 表格上下文
     * @return 合并信息数组
     * @throws TableException 操作失败时抛出
     */
    public TableMergeInfo[] getTableMergeInfo(TableContext context) throws TableException {
        logger.debug("获取工作表的合并信息: {}", context.getTableBlockId());

        Block tableBlock = context.getTableBlock();
        if (tableBlock.getSheet() == null) {
            throw new TableException("块中未找到电子表格信息");
        }

        String token = tableBlock.getSheet().getToken();
        if (token == null || token.isEmpty()) {
            logger.debug("电子表格令牌为空,无可用合并信息");
            return null;
        }

        try {
            // 解析token获取spreadsheetToken和sheetId
            String[] parts = SheetCoordinateHelper.parseSheetToken(token);
            String spreadsheetToken = parts[0];
            String sheetId = parts[1];

            // 如果sheetId为空，需要获取默认sheet的ID
            if (sheetId.isEmpty()) {
                // querySheets现在直接返回Sheet[]，失败时抛出FeishuApiException
                com.lark.oapi.service.sheets.v3.model.Sheet[] sheets =
                    client.sheets().querySheets(spreadsheetToken);

                if (sheets != null && sheets.length > 0) {
                    sheetId = sheets[0].getSheetId();
                } else {
                    logger.warn("无法确定工作表ID以获取合并信息");
                    return null;
                }
            }

            // 获取Sheet信息，包含合并单元格信息
            // getSheet现在直接返回Sheet对象，失败时抛出FeishuApiException
            com.lark.oapi.service.sheets.v3.model.Sheet sheetData =
                client.sheets().getSheet(spreadsheetToken, sheetId);

            if (sheetData != null) {

                // 获取合并单元格信息
                com.lark.oapi.service.sheets.v3.model.MergeRange[] merges = sheetData.getMerges();

                if (merges != null && merges.length > 0) {
                    // 获取表格维度
                    int[] dimensions = getTableDimensions(context);
                    int rowCount = dimensions[0];
                    int columnCount = dimensions[1];

                    // 创建与单元格数量对应的TableMergeInfo数组
                    // 与普通表格保持一致的格式
                    TableMergeInfo[] mergeInfos = new TableMergeInfo[rowCount * columnCount];

                    // 遍历所有合并区域
                    for (com.lark.oapi.service.sheets.v3.model.MergeRange merge : merges) {
                        int startRow = merge.getStartRowIndex();
                        int endRow = merge.getEndRowIndex();
                        int startCol = merge.getStartColumnIndex();
                        int endCol = merge.getEndColumnIndex();

                        int rowSpan = endRow - startRow + 1;
                        int colSpan = endCol - startCol + 1;

                        // 为合并区域内的所有单元格设置合并信息
                        for (int r = startRow; r <= endRow && r < rowCount; r++) {
                            for (int c = startCol; c <= endCol && c < columnCount; c++) {
                                int cellIndex = r * columnCount + c;

                                if (r == startRow && c == startCol) {
                                    // 合并区域的起始单元格
                                    mergeInfos[cellIndex] = TableMergeInfo.newBuilder()
                                            .rowSpan(rowSpan)
                                            .colSpan(colSpan)
                                            .build();
                                } else {
                                    // 被合并的单元格
                                    mergeInfos[cellIndex] = TableMergeInfo.newBuilder()
                                            .rowSpan(0)
                                            .colSpan(0)
                                            .build();
                                }
                            }
                        }

                        logger.debug("Found merge at [{},{}] with span {}x{}",
                                   startRow, startCol, rowSpan, colSpan);
                    }

                    logger.info("在工作表中找到{}个合并区域", merges.length);
                    return mergeInfos;
                } else {
                    logger.debug("工作表中未找到合并区域");
                    return null;
                }
            }

            // sheetData为null时返回null
            return null;

        } catch (Exception e) {
            logger.error("获取合并信息失败: {}", e.getMessage());
            // 不抛出异常，返回null表示没有合并信息
            return null;
        }
    }

    /**
     * 转换为TableData对象
     *
     * @param context 表格上下文
     * @return TableData对象
     * @throws TableException 操作失败时抛出
     */
    public TableData convertToTableData(TableContext context) throws TableException {
        logger.debug("将工作表转换为表格数据: {}", context.getTableBlockId());

        Block tableBlock = context.getTableBlock();
        if (tableBlock.getSheet() == null) {
            throw new TableException("块中未找到电子表格信息");
        }

        Sheet sheet = tableBlock.getSheet();
        String token = sheet.getToken();

        if (token == null || token.isEmpty()) {
            // 没有token，返回空的TableData
            TableData tableData = new TableData();
            return tableData;
        }

        try {
            // 解析token获取spreadsheetToken和sheetId
            String[] parts = SheetCoordinateHelper.parseSheetToken(token);
            String spreadsheetToken = parts[0];
            String sheetId = parts[1];

            // 如果sheetId为空，需要获取默认sheet的ID
            if (sheetId.isEmpty()) {
                // querySheets现在直接返回Sheet[]，失败时抛出FeishuApiException
                com.lark.oapi.service.sheets.v3.model.Sheet[] sheets =
                    client.sheets().querySheets(spreadsheetToken);

                if (sheets != null && sheets.length > 0) {
                    sheetId = sheets[0].getSheetId();
                } else {
                    throw new TableException("无法确定电子表格的工作表ID: " + spreadsheetToken);
                }
            }

            // 获取表格维度
            int[] dimensions = getTableDimensions(context);
            int rows = dimensions[0];
            int cols = dimensions[1];

            logger.debug("将工作表{}转换为表格数据({} x {})", token, rows, cols);

            // 创建TableData对象
            TableData tableData = new TableData();

            if (rows > 0 && cols > 0) {
                // 构建完整范围（使用A1表示法）
                String range = String.format("%s!A1:%s%d", sheetId, SheetCoordinateHelper.getColumnLetter(cols - 1), rows);

                logger.debug("从范围读取工作表数据: {}", range);

                // 读取所有数据
                List<List<String>> values = client.sheets().getValues(spreadsheetToken, range);

                if (values != null && !values.isEmpty()) {
                    // 转换为RowData列表
                    List<RowData> rowDataList = new ArrayList<>();

                    for (List<String> row : values) {
                        // 确保每行都有足够的列
                        List<String> cells = new ArrayList<>(row);
                        while (cells.size() < cols) {
                            cells.add("");
                        }
                        rowDataList.add(new RowData(cells));
                    }

                    // 如果读取的行数少于维度中的行数，补充空行
                    while (rowDataList.size() < rows) {
                        List<String> emptyCells = new ArrayList<>();
                        for (int i = 0; i < cols; i++) {
                            emptyCells.add("");
                        }
                        rowDataList.add(new RowData(emptyCells));
                    }

                    tableData.setRows(rowDataList);

                    logger.info("成功将工作表转换为包含{}行的表格数据", rowDataList.size());
                } else {
                    // 创建空的表格结构
                    List<RowData> emptyRows = new ArrayList<>();
                    for (int i = 0; i < rows; i++) {
                        List<String> cells = new ArrayList<>();
                        for (int j = 0; j < cols; j++) {
                            cells.add("");
                        }
                        emptyRows.add(new RowData(cells));
                    }
                    tableData.setRows(emptyRows);

                    logger.debug("创建空表格数据结构 for sheet");
                }
            } else {
                // 空表格
                tableData.setRows(new ArrayList<>());
                logger.debug("电子表格没有行或列");
            }

            return tableData;

        } catch (TableException e) {
            throw e;
        } catch (Exception e) {
            logger.error("将工作表转换为表格数据失败: {}", e.getMessage());
            throw new TableException("将工作表转换为表格数据失败: " + e.getMessage());
        }
    }

    /**
     * 从Block构建TableData（Sheet不使用Block存储数据）
     *
     * @param tableBlock 表格Block
     * @param blockMap Block映射（未使用）
     * @return TableData对象
     * @throws TableException 操作失败时抛出
     */
    public TableData buildTableFromBlocks(Block tableBlock, Map<String, Block> blockMap)
            throws TableException {
        if (tableBlock == null || tableBlock.getSheet() == null) {
            return new TableData();
        }

        // Sheet不使用Block结构存储数据
        // 数据存储在外部的电子表格文档中
        Sheet sheet = tableBlock.getSheet();
        String token = sheet.getToken();

        logger.info("电子表格 {} data is stored externally, not in blocks", token);

        TableData tableData = new TableData();

        // 设置维度信息
        if (sheet.getRowSize() != null && sheet.getColumnSize() != null) {
            // 创建空的表格结构
            List<RowData> rows = new ArrayList<>();
            for (int i = 0; i < sheet.getRowSize(); i++) {
                List<String> cells = new ArrayList<>();
                for (int j = 0; j < sheet.getColumnSize(); j++) {
                    cells.add("");
                }
                rows.add(new RowData(cells));
            }
            tableData.setRows(rows);
        }

        return tableData;
    }
}
